import { createAsyncThunk, createSlice, isRejected } from "@reduxjs/toolkit";
import { GetParams, PageInfo, Supplier, SupplierEntry, int } from "../types";
import { deleteRequest, getRequest, postRequest, putRequest } from "../util/Net";
import { RootState } from "./store";

// 1. Requests.

type GetSupplierRequest = GetParams & {
  name?: string;
};

type SupplierRequest = Supplier;

interface DeleteSupplierRequest {
  id: string;
}

// 2. Responses.

type GetSupplierResponseEntry = SupplierEntry;

type GetSupplierResponse = PageInfo<GetSupplierResponseEntry>;

// 3. Params for reducers.

type GetSupplierParams = GetParams & {
  name?: string;
};

type CreateSupplierParams = Supplier;

type UpdateSupplierParams = SupplierEntry;

interface DeleteSupplierParams {
  id: int[];
}

// 4. State and initial value definition.

interface SupplierManagementState {
  entries: SupplierEntry[];
  loaded: boolean;
}

const initialState: SupplierManagementState = {
  entries: [],
  loaded: false
};

// 5. Async functions definition.

const getSupplier = createAsyncThunk('/supplier/get', async (params: GetSupplierParams) => {
  const response = await getRequest<GetSupplierResponse, GetSupplierRequest>({
    url: '/supplier',
    params: params
  });
  return response.data;
});

const createSupplier = createAsyncThunk('/supplier/post', async (params: CreateSupplierParams) => {
  const response = await postRequest<null, SupplierRequest>({
    url: '/supplier',
    request: params
  });
  return response.data;
});

const updateSupplier = createAsyncThunk('/supplier/put', async (params: UpdateSupplierParams) => {
  const response = await putRequest<null, SupplierRequest>({
    url: `/supplier/${params.id}`,
    request: {
      name: params.name,
      contact: params.contact,
      phone: params.phone,
      email: params.email,
      address: params.address
    }
  });
  return response.data;
});

const deleteSupplier = createAsyncThunk('/supplier/delete', async (params: DeleteSupplierParams) => {
  const response = await deleteRequest<null, null, DeleteSupplierRequest>({
    url: '/supplier',
    params: {
      id: params.id.join(',')
    }
  });
  return response.data;
});

// 6. Slice definition.

const supplierManagementSlice = createSlice({
  name: 'supplierManagement',
  initialState: initialState,
  reducers: {
    clear: (state) => {
      state.entries = [];
      state.loaded = false;
    },
    refresh: (state) => {
      state.loaded = false;
    }
  },
  extraReducers: (builder) => {
    builder.addCase(getSupplier.fulfilled, (state, action) => {
      state.entries = action.payload.result.data;
      state.loaded = true;
    }).addCase(createSupplier.fulfilled, (state) => {
      state.loaded = false;
    }).addCase(updateSupplier.fulfilled, (state) => {
      state.loaded = false;
    }).addCase(deleteSupplier.fulfilled, (state) => {
      state.loaded = false;
    }).addMatcher(isRejected, (state, action) => {
      console.error(action.error);
    });
  }
});

export default supplierManagementSlice.reducer;
export const supplierManagementActions = { ...supplierManagementSlice.actions, getSupplier, createSupplier, updateSupplier, deleteSupplier };
export const selectSupplierEntries = (root: RootState) => root.supplierManagementReducer.entries;
export const selectSupplierEntriesLoaded = (root: RootState) => root.supplierManagementReducer.loaded;